﻿using Newtonsoft.Json;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Zocono.Infrastructure.Common;
using Zocono.WCS.Domain.DomainRepository;
using Zocono.WCS.Domain.EntityInfo;
using Zocono.WCS.Domain.LogDomain;
using Zocono.WCS.Domain.PlcBytesObject;
using Zocono.WCS.Domain.PlcConnectPoolDomain;
using Zocono.WCS.Domain.ProcessModuleDomain;
using Zocono.WCS.Infrastructure.ApllicationDto.Enums;
using Zocono.WCS.Infrastructure.PlcCommon;

namespace Zocono.WCS.Domain.EquipmentProcessDomain.PlanarGeneralMessage
{
    public class ElevatorRouteService : IPlanarGeneralPlcActionProcessService
    {

        private readonly IPlcConnectionPool _PlcConnectionPool;
        private readonly IWorkTaskInfoRepository _WorkTaskInfoRepository;
        private readonly IPlcWriteDbInfoRepository _PlcWriteDbInfoRepository;
        private readonly IPlcReadDbInfoRepository _PlcReadeDbInfoRepository;
        private readonly IPlcConnectionInfoRepository _PlcConnectionInfoRepository;
        private readonly IPlcConnectionStateInfoRepository _IPlcConnectionStateInfoRepository;
        private readonly IRunLogInfoService _IRunLogInfoService;
        public ElevatorRouteService(IPlcConnectionPool plcConnectionPool
                , IWorkTaskInfoRepository workTaskInfoRepository
                , IPlcWriteDbInfoRepository plcWriteDbInfoRepository,
                IPlcConnectionInfoRepository plcConnectionInfoRepository
                , IPlcConnectionStateInfoRepository plcConnectionStateInfoRepository
            , IPlcReadDbInfoRepository plcReadDbInfoRepository
            , IRunLogInfoService iRunLogInfoService)
        {
            _PlcConnectionPool = plcConnectionPool;
            _WorkTaskInfoRepository = workTaskInfoRepository;
            _PlcWriteDbInfoRepository = plcWriteDbInfoRepository;
            _PlcConnectionInfoRepository = plcConnectionInfoRepository;
            _IPlcConnectionStateInfoRepository = plcConnectionStateInfoRepository;
            _PlcReadeDbInfoRepository = plcReadDbInfoRepository;
            _IRunLogInfoService = iRunLogInfoService;
        }


        public async Task ProcessActionMessageAsync(BytesObjectBase plcActionMessage, BytesObjectBase wcsActionMessage, EquipmentDbObject planarEquipmentDbObject)
        {
            var plcMessage = plcActionMessage as PlanarGeneralPlcActionBO;//Plc的动作报文
            var wcsMessage = wcsActionMessage as PlanarGeneralWcsActionBO;//Wcs的动作报文
            //var plcStateBo = plcStateMassge as PlcOnLineStateBO;//Plc在线离线报文 没有设备信息
            plcMessage.PalletBarcode = plcMessage.PalletBarcode.Trim();
            PlanarGeneralWriteWcsAction writeBo = null;//写入Plc的报文
            PlcConnectionS7 plcConn = _PlcConnectionPool.S7GetWritePlcConnection(plcMessage.PlcConnectionID);//plc写入连接（不锁定）


            RunLogInfo runLogInfo = new RunLogInfo();
            runLogInfo.ContainerBarcode = plcMessage.PalletBarcode;
            runLogInfo.EquipmentCode = plcMessage.EquipmentCode;
            runLogInfo.RunType = "跨楼层";

            runLogInfo.RunLog = "到达十字路口-提升机前任务开始";
            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);

            //1. 验证plc是否在线
            var plcIPStates = await _IPlcConnectionStateInfoRepository.GetFirstAsync(l => l.PlcConnectionID == plcMessage.PlcConnectionID && l.Connected == true);
            if (plcIPStates == null)
            {
                runLogInfo.RunLog = $"{plcConn.IP}plc已离线";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }

            if (plcMessage.AlrmCode != 0)
            {
                runLogInfo.RunLog = $"报警,报警代码：{plcMessage.AlrmCode}";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }
            #region plc写入连接获取&写入报文构建
            //Plc连接Id
            long plcId = wcsMessage.PlcConnectionID;
            //写入plc的报文配置获取
            var objectType = typeof(PlanarGeneralWriteWcsAction).Name;
            var writeConfig = await _PlcWriteDbInfoRepository.GetFirstAsync(s => s.EquipmentCode == plcMessage.EquipmentCode && s.ObjectType == objectType);
            if (writeConfig == null)
            {
                runLogInfo.RunLog = $"获取PLC写入配置失败";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }

            //构建写入报文
            writeBo = new PlanarGeneralWriteWcsAction(
                writeConfig.PlcConnectionId,
                writeConfig.ID,
                writeConfig.DbCode,
                writeConfig.DbStart,
                objectType,
                //writeConfig.EquipmentCode.ToInt32(),
                plcMessage.EquipmentCode.ToInt32(),
                plcMessage.ActionType,
                plcMessage.ToEquipmentCode,
                taskCode: plcMessage.TaskCode,
                palletBarcode: plcMessage.PalletBarcode,
                plcMessage.PalletType,
                alrmCode: plcMessage.AlrmCode);

            if (plcConn == null)
            {
                runLogInfo.RunLog = $"获取PLC连接失败";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }
            #endregion

            //3. 验证wcs任务，验证wcs当前子任务
            var exp = Expressionable.Create<WorkTaskInfo>();
            exp.AndIF(plcMessage.TaskCode > 0, it => it.TaskCode == plcMessage.TaskCode);
            exp.AndIF(true, it => it.PalletCode == plcMessage.PalletBarcode && it.TaskState == EnumTaskState.Executing);
            var task = await _WorkTaskInfoRepository.GetFirstAsync(exp.ToExpression());
            if (task == null)
            {
                runLogInfo.RunLog = $"任务号({plcMessage.TaskCode})执行中的任务数据未查到";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);

                writeBo.ActionType = 0;
                writeBo.AlrmCode = 7;
                var writeflag = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                if (writeflag == false)
                {
                    runLogInfo.RunLog = $"无任务报警：设备编号{writeBo.EquipmentCode})写入报文失败";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }
                else
                {
                    runLogInfo.RunLog = $"无任务报警：设备编号{writeBo.EquipmentCode})写入报文成功";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                }
                return;
            }
            //托盘类型
            switch (task.PalletCode.Substring(1, 1))
            {
                case "A":
                    writeBo.PalletType = 2;
                    break;
                case "B":
                    writeBo.PalletType = 1;
                    break;
                case "C":
                    writeBo.PalletType = 3;
                    break;
            }


            var routeDetailExp = Expressionable.Create<RouteDetailInfo>();
            routeDetailExp.AndIF(true, l => l.ID == task.CurrentRounteDetailID);
            var routeDetail = await _WorkTaskInfoRepository.AsSugarClient()
                .Queryable<RouteDetailInfo>()
                .Where(routeDetailExp.ToExpression())
                .Select(l => l)
                .FirstAsync();

            if (routeDetail == null)
            {
                writeBo.ActionType = 0;
                writeBo.AlrmCode = 6;
                var writeflag = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());
                runLogInfo.RunLog = $"巷道路径详情配置信息起始工位{task.WmsFromStation}目标工位{task.WmsToStation}获取设备路径失败";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                return;
            }


            //跨楼层主要处理（后续跨楼层的配置可在plcreadinfo和routeDetailinfo表中加字段，或独立表）
            if (task.CurrentFromEquipment.Substring(0, 1) != task.CurrentToEquipment.Substring(0, 1))
            {
                try
                {
                    var plcConfigDD = await _PlcReadeDbInfoRepository.GetFirstAsync(l => l.ID == plcMessage.PlcReadDbID);

                    //一楼回库回拉线需要小于提升机来分配
                    //需要判断下一个口的状态
                    if (routeDetail.FromCargo.ToInt32() < plcConfigDD.PlcName.ToInt32() && (routeDetail.ToCargo.ToInt32() > plcConfigDD.PlcName.ToInt32() || routeDetail.ToCargo.ToInt32() == 0))
                    {
                        var plcConfigleft = await _PlcReadeDbInfoRepository.GetFirstAsync(l => l.EquipmentCode == (plcConfigDD.EquipmentCode.ToInt32() - 2).ToString());
                        byte[] bytes = await plcConn.ReadDbAsync(plcConfigleft.DbCode, plcConfigleft.DbStart, plcConfigleft.DbLength);
                        if (bytes == null)
                        {
                            runLogInfo.RunLog = $"读DB失败";
                            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                            return;
                        }
                        PlanarGeneralPlcActionBO plcActionDO = new();
                        plcActionDO.Serialize(plcConfigleft.PlcConnectionID, plcConfigleft.ID, plcConfigleft.DbStart, plcConfigleft.DbLength, plcConfigleft.DbStart, plcConfigleft.DbLength, "PlanarGeneralPlcActionBO", plcConfigleft.EquipmentCode, bytes);//主要是bytes转化成明文
                        if (plcActionDO.PalletBarcode.Trim().Length == 0)
                        {
                            writeBo.ActionType = 11;
                        }
                        else
                        {
                            writeBo.ActionType = 12;
                        }
                    }
                    else if (routeDetail.FromCargo.ToInt32() > plcConfigDD.PlcName.ToInt32())
                    {
                        writeBo.ActionType = 12;
                    }
                    else
                    {
                        writeBo.ActionType = 11;
                    }
                    //最后一个提升机直接入
                    //if (routeDetail.ToCargo.ToInt32() == plcConfigDD.PlcName.ToInt32())
                    //{
                    //    writeBo.ActionType = 11;
                    //}

                }
                catch (Exception ex)
                {
                    runLogInfo.RunLog = $"分配提升机发生异常{ex}";
                    await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
                    return;
                }


            }

            //写入正常报文
            writeBo.TaskCode = task.TaskCode;
            writeBo.PalletBarcode = task.PalletCode;
            writeBo.ToEquipmentCode = task.CurrentToEquipment.ToInt32();
            var writeBl = await plcConn.WriteDbAsync(writeBo.DbCode, writeBo.DbStart, writeBo.Deserialize());

            runLogInfo.RunLog = $"写入PLC报文{JsonConvert.SerializeObject(writeBo)}";
            await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            if (!writeBl)
            {
                runLogInfo.RunLog = $"写入正常报文失败";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            }
            else
            {
                runLogInfo.RunLog = $"写入正常报文成功";
                await _IRunLogInfoService.AddRunLogInfoAsync(runLogInfo);
            }
        }
    }
}
